﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Nancy;
using Nancy.TinyIoc;
using Nancy.Bootstrapper;
using Nancy.Responses;
using System.IO;
using Nancy.Conventions;
using System.IO.Compression;

namespace NancyApp
{
    public class CustomBootstrapper : DefaultNancyBootstrapper
    {
        protected override void ApplicationStartup(TinyIoCContainer container, IPipelines pipelines)
        {
            base.ApplicationStartup(container, pipelines);

            pipelines.BeforeRequest += (ctx) =>
            {
                if (ctx.Request.Path.Contains("needpermit"))
                {  
                    if (ctx.Request.Query["userid"] == null)
                    {
                        throw new Exception("no power to access");
                    }
                }
                return null;
            };            

            pipelines.OnError += (ctx, ex) =>
            {
                if (ex != null)
                {
                    Response x = new JsonResponse<object>(new { id = 1, msg = ex.Message }, new DefaultJsonSerializer());
                    if (ctx.Request.Query["callback"] != null)
                    {
                        string str = string.Empty;
                        using (var memory = new MemoryStream())
                        {
                            x.Contents.Invoke(memory);
                            str = Encoding.UTF8.GetString(memory.ToArray());
                        }

                        x.Contents = y =>
                        {
                            using (var writer = new StreamWriter(y))
                            {
                                string callback = ctx.Request.Query["callback"];
                                writer.Write(callback + "(" + str + ")");
                            }
                        };
                    }
                    return x;
                }
                return null;
            };

            pipelines.AfterRequest.InsertItemAtPipelineIndex(0, ctx =>
            {
                var compresses = ctx.Request.Headers.AcceptEncoding;
                if (compresses != null && compresses.Count() > 1)
                {
                    string str = string.Empty;
                    using (var memory = new MemoryStream())
                    {
                        ctx.Response.Contents.Invoke(memory);
                        str = Encoding.UTF8.GetString(memory.ToArray());
                    }

                    var compress = compresses.FirstOrDefault();
                    if(compress.Contains("gzip"))
                    {
                        ctx.Response.Contents = stream =>
                        {
                            using (var gzip = new GZipStream(stream, CompressionMode.Compress))
                            {
                                using (var sw = new StreamWriter(gzip))
                                {
                                    sw.Write(str);
                                }
                                gzip.Flush();
                            }
                        };
                        ctx.Response.Headers.Add("Content-Encoding", "gzip");
                    }
                }
            });

            

            Jsonp.Enable(pipelines);
        }

        protected override void RequestStartup(TinyIoCContainer container, IPipelines pipelines, NancyContext context)
        {
            base.RequestStartup(container, pipelines, context);
        }

        protected override void ConfigureConventions(NancyConventions nancyConventions)
        {
            base.ConfigureConventions(nancyConventions);

            nancyConventions.StaticContentsConventions.Clear();
            nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("css", "/content/css"));
            nancyConventions.StaticContentsConventions.Add(StaticContentConventionBuilder.AddDirectory("js", "/content/js"));
        }
    }
}